package org.jupiter.blog.service.service.impl;

import org.jupiter.blog.api.common.TdesignTreeNode;
import org.jupiter.blog.api.convertor.JupiterPermissionStructConvertor;
import org.jupiter.blog.api.domain.JupiterPermission;
import org.jupiter.blog.api.dto.JupiterPermissionDTO;
import org.jupiter.blog.service.mapper.JupiterPermissionMapper;
import org.jupiter.blog.service.service.JupiterPermissionService;
import org.jupiter.blog.service.service.JupiterPermissionUrlService;
import org.jupiter.blog.api.dto.JupiterPermissionUrlDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;

@Service
public class JupiterPermissionServiceImpl implements JupiterPermissionService {

	@Autowired
	private JupiterPermissionMapper permissionMapper;

	@Autowired
	private JupiterPermissionStructConvertor permissionConvertor;

	@Autowired
	private JupiterPermissionUrlService permissionUrlService;

	@Override
	@Transactional
	public void createPermission(JupiterPermissionDTO dto) {
		JupiterPermission permission = permissionConvertor.toEntity(dto);
		if (!StringUtils.hasText(permission.getUuid())){
			String uuid = UUID.randomUUID().toString();
			permission.setUuid(uuid);
			// 将生成的UUID设置回DTO中
			dto.setUuid(uuid);
		}
		permission.setCreateTime(LocalDateTime.now());
		permission.setUpdateTime(LocalDateTime.now());
		permissionMapper.insert(permission);
	}

	@Override
	@Transactional(readOnly = true)
	public JupiterPermissionDTO getById(String uuid) {
		JupiterPermission permission = permissionMapper.selectByUuid(uuid);
		JupiterPermissionDTO dto = permissionConvertor.toDto(permission);

		// 获取关联的URL资源
		if (dto != null){
			List<String> urlResourceUuids = getPermissionUrlResources(uuid);
			dto.setUrlResourceUuids(urlResourceUuids);
		}

		return dto;
	}

	@Override
	@Transactional
	public void updatePermission(String uuid, JupiterPermissionDTO dto) {
		JupiterPermission permission = permissionConvertor.toEntity(dto);
		permission.setUuid(uuid);
		permission.setUpdateTime(LocalDateTime.now());
		permissionMapper.updateByUuidSelective(permission);

		// 更新URL资源关联
		if (dto.getUrlResourceUuids() != null){
			assignUrlsToPermission(uuid, dto.getUrlResourceUuids());
		}
	}

	@Override
	@Transactional
	public void deletePermission(String uuid) {
		// 删除关联的URL资源
		permissionUrlService.deleteByPermissionUuid(uuid);

		// 删除权限
		permissionMapper.deleteByUuid(uuid);
	}

	@Override
	@Transactional
	public void restorePermission(String uuid) {
		permissionMapper.restoreByUuid(uuid);
	}

	@Override
	@Transactional(readOnly = true)
	public List<JupiterPermissionDTO> getByPage(JupiterPermissionDTO queryDTO) {
		int offset = (queryDTO.getPage() - 1) * queryDTO.getSize();
		List<JupiterPermission> permissions = permissionMapper.selectByPage(
				queryDTO.getName(),
				queryDTO.getCode(),
				queryDTO.getType(),
				offset,
				queryDTO.getSize()
		);
		return permissionConvertor.toDtoList(permissions);
	}

	@Override
	@Transactional(readOnly = true)
	public long getCount(JupiterPermissionDTO queryDTO) {
		return permissionMapper.countByQuery(queryDTO.getName(), queryDTO.getCode(), queryDTO.getType());
	}

	@Override
	@Transactional(readOnly = true)
	public List<JupiterPermissionDTO> getAll() {
		List<JupiterPermission> permissions = permissionMapper.selectAll();
		return permissionConvertor.toDtoList(permissions);
	}

	@Override
	@Transactional(readOnly = true)
	public List<TdesignTreeNode> getTree() {
		List<JupiterPermission> permissions = permissionMapper.selectTree();
		return this.toTree(permissions);
	}

	@Override
	@Transactional(readOnly = true)
	public List<JupiterPermissionDTO> getByRoleId(String roleId) {
		List<JupiterPermission> permissions = permissionMapper.selectByRoleId(roleId);
		return permissionConvertor.toDtoList(permissions);
	}

	@Override
	@Transactional(readOnly = true)
	public boolean existsByCode(String code) {
		return permissionMapper.countByCode(code) > 0;
	}

	public List<TdesignTreeNode> toTree(List<JupiterPermission> permissions) {
		// 先按 parentUuid 分组
		Map<String, List<JupiterPermission>> map = permissions.stream()
				.filter(p -> p.getParentUuid() != null)
				.collect(Collectors.groupingBy(JupiterPermission::getParentUuid));

		List<TdesignTreeNode> roots = new ArrayList<>();
		for (JupiterPermission perm : permissions){
			if (perm.getParentUuid() == null){ // 根节点
				roots.add(this.buildNode(perm, map));
			}
		}
		return roots;
	}

	private TdesignTreeNode buildNode(JupiterPermission perm, Map<String, List<JupiterPermission>> map) {
		TdesignTreeNode node = new TdesignTreeNode();
		node.setValue(perm.getUuid());
		node.setLabel(perm.getName());

		List<JupiterPermission> children = map.get(perm.getUuid());
		if (children != null){
			List<TdesignTreeNode> childNodes = children.stream()
					.map(child -> buildNode(child, map))
					.collect(Collectors.toList());
			node.setChildren(childNodes);
		}
		return node;
	}

	@Override
	@Transactional
	public void assignUrlsToPermission(String permissionUuid, List<String> urlResourceUuids) {
		permissionUrlService.assignUrlsToPermission(permissionUuid, urlResourceUuids);
	}

	@Override
	@Transactional(readOnly = true)
	public List<String> getPermissionUrlResources(String permissionUuid) {
		List<JupiterPermissionUrlDTO> permissionUrls = permissionUrlService.getByPermissionUuid(permissionUuid);
		return permissionUrls.stream()
				.map(JupiterPermissionUrlDTO::getUrlResourceUuid)
				.collect(Collectors.toList());
	}

	@Override
	@Transactional
	public void createPermissionWithUrls(JupiterPermissionDTO dto) {
		// 直接创建权限实体，避免内部方法调用
		JupiterPermission permission = permissionConvertor.toEntity(dto);
		if (!StringUtils.hasText(permission.getUuid())){
			String uuid = UUID.randomUUID().toString();
			permission.setUuid(uuid);
			// 将生成的UUID设置回DTO中
			dto.setUuid(uuid);
		}
		permission.setCreateTime(LocalDateTime.now());
		permission.setUpdateTime(LocalDateTime.now());
		permissionMapper.insert(permission);

		// 分配URL资源
		if (dto.getUrlResourceUuids() != null && !dto.getUrlResourceUuids().isEmpty()){
			assignUrlsToPermission(dto.getUuid(), dto.getUrlResourceUuids());
		}
	}
}
